package com.yand.data.map;


public class MyMap<K, V> {
    private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private float loadFactor = 0;
    private int initCapacity = 0;
    private Entry<K, V>[] table = null;

    public MyMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        this.initCapacity = DEFAULT_INITIAL_CAPACITY;
        table = new Entry[this.initCapacity];
    }

    public MyMap(int initCapacity, float loadFactor) {
        this.loadFactor = loadFactor;
        this.initCapacity = initCapacity;
        table = new Entry[this.initCapacity];
    }

    private int hash(K key) {
        int h;
        return (key == null) ? 0 : Math.abs((h = key.hashCode())) ^ (h >>> 16);
    }


    public V put(K key, V value) {
        int index = hash(key) % initCapacity;
        if (table[index] != null) {
            Entry<K, V> e = table[index];
            Entry<K, V> e2 = null;
            while (e != null) {
                if (hash(e.key) == hash(key) && e.key.equals(key)) {
                    e.value = value;
                    return value;
                }
                e2 = e;
                e = e.next;
            }
            e2.next = new Entry<>(key, value, null, index);
        } else {
            Entry<K, V> e = new Entry<>(key, value, null, index);
            table[index] = e;
        }
        return value;
    }


    public V get(K key) {
        int index = hash(key) % initCapacity;
        Entry<K, V> e = table[index];
        if (e == null) {
            return null;
        }

        while (e != null) {
            if (e.key == null && key == null ||
                    hash(e.key) == hash(key) && e.key.equals(key)) {
                return e.value;
            }
            e = e.next;
        }
        return null;
    }



    class Entry<K, V> {

        K key;

        V value;

        Entry<K, V> next;

        int index;//记录下标

        Entry(K k, V v, Entry<K, V> next, int inx) {
            this.key = k;
            this.value = v;
            this.index = inx;
            this.next = next;
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        public Entry getNext() {
            return next;
        }
    }

}
